﻿/* AgileFx Version 1.0
 * An open-source framework for rapid development of applications and services using Microsoft.net
 * Developed by: AgileHead
 * Website: www.agilefx.org
 * This component is licensed under the terms of the Apache 2.0 License.
 */

using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Reflection;

namespace AgileFx.EF.ModificationTypes
{
    public class EntityUpdation<TContainer, TElement> : Modification<TContainer, TElement>
        where TContainer : EntityObject, new()
        where TElement : EntityObject, new()
    {        
        public Action<TElement> EntityUpdates { get; set; }
        
        public EntityUpdation(Expression<Func<TContainer, TElement>> fieldSelector, Action<TElement> entityUpdate,
            IModification[] innerUpdates)
        {
            this.FieldReference = new FieldReference<TContainer,TElement>(fieldSelector);
            this.EntityUpdates = entityUpdate;
            if (null != innerUpdates) EntityFieldModifications.AddRange(innerUpdates);
        }

        public EntityUpdation(Expression<Func<TContainer, IEnumerable<TElement>>> collectionSelector, Action<TElement> entityUpdate,
            IModification[] innerUpdates)
        {
            this.FieldReference = new FieldReference<TContainer,TElement>(collectionSelector);
            this.EntityUpdates = entityUpdate;
            if (null != innerUpdates) EntityFieldModifications.AddRange(innerUpdates);
        }

        public void ApplyUpdates(TElement obj)
        {
            if (null != this.EntityUpdates)
            {
                this.EntityUpdates(obj);
                this.EntityUpdates = null;
            }
        }

        public override ModificationType Type
        {
            get
            {
                return ModificationType.Modification;
            }
        }

        public override object _applyChanges(object container, DbContext context)
        {
            //Apply Updates on the element.
            var element = GetElement(container, context);

            if (element is IContextAware && element != null)
                (element as IContextAware).Context = context;

            if (null != EntityUpdates) ApplyUpdates(element);
            FieldReference.SetValue(container, element);
            ApplyInnerModifications(element, context);
            return element;
        }
    }
}
